#include <iostream>
#include <vector>
#include "Pthread.hpp"
#include <unistd.h>
using namespace std;
#define NUM 4
// 锁本身是全局的，那么锁也是共享资源！谁保证锁的安全
// pthread_mutex:加锁和解锁被设计成原子的了
// 2. 如何看待锁呢？二元信号量就是锁！
//    2.1 加锁本质就是对资源展开预定
// pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
int ticketnum = 10000; // 共享资源,临界资源


// class ThreadData
// {
// public:
//     std::string name;
//     pthread_mutex_t *lock_ptr;
// };
// void Ticket(ThreadData &td)
// {
//     while (true)
//     {
//         pthread_mutex_lock(td.lock_ptr);
//         if(ticketnum > 0)
//         {
//             usleep(1000);
//             //抢票
//             printf("I am %s ,get a new ticket,id: %d\n",td.name.c_str() ,ticketnum--);

//             pthread_mutex_unlock(td.lock_ptr);
//         }
//         else
//         {
//             pthread_mutex_unlock(td.lock_ptr);
//             break;
//         }
//     }
    
// }
// int main()
// {
//     pthread_mutex_t lock;
//     pthread_mutex_init(&lock,nullptr);

//     // 1. 构建线程对象
//     vector<MyThread::Thread<ThreadData>> threads;
//     for(int i = 0; i < NUM; i++)
//     {
//         ThreadData *td = new ThreadData();
//         td->lock_ptr = &lock;
//         threads.emplace_back(Ticket, *td);
//         td->name = threads.back().Name();
//     }

//     // 2. 开始线程
//     for(auto &thread : threads)
//     {
//         thread.Start();
//     }

//     // 3. 等待线程
//     for(auto &thread : threads)
//     {
//         thread.Join();
//     }

//     pthread_mutex_destroy(&lock);
//     return 0;
// }

void Ticket()
{
    while (true)
    {
        if(ticketnum > 0)
        {
            usleep(1000);
            //抢票
            printf("get a new ticket,id: %d\n",ticketnum--);
        }
        else
        {
            break;
        }
    }
    
}
int main()
{
    // 1. 构建线程对象，MyThread: 上篇文章有模拟thread库的代码
    vector<MyThread::Thread<int>> threads;
    for(int i = 0; i < NUM; i++)
    {
        threads.emplace_back(Ticket);
    }

    // 2. 开始线程
    for(auto &thread : threads)
    {
        thread.Start();
    }

    // 3. 等待线程
    for(auto &thread : threads)
    {
        thread.Join();
    }
    return 0;
}


